import argparse
import cv2
import numpy as np


def BinStr2DecInt(s: str, num_of_bytes: int) -> int:
    """
    长度为8的二进制01字符串转十进制整数
    :param s: str
    :param num_of_bytes: int 字节位数
    :return: res: int
    """
    res = 0
    s = s[::-1]
    for i in range(8 * num_of_bytes):
        if s[i] == '1':
            res += 2 ** i
    return res


def decode(bin_file: str, num_of_frames: int):
    fileSave = open(bin_file, 'wb')
    s = ''
    flag = False
    state = 0
    len_len1 = 0
    left_len = 0
    crcs = []
    for k in range(num_of_frames):
        image = cv2.imread('res/res' + str(k) + '.png')
        rows, cols, channels = image.shape
        # 图像解码成二进制文件
        for row in range(15, rows - 15, 3):
            for col in range(15, cols - 15, 3):
                a = image[row, col]
                s += '1' if a[0] > 127 and a[1] > 127 and a[2] > 127 else '0'
                if len(s) == 8:
                    res = BinStr2DecInt(s, 1)
                    if res == 0xCC and not flag:
                        # 表示转义字符
                        left_len -= 8
                        flag = True
                        s = ''
                        continue
                    elif res == 0xCA and not flag:  # 表示帧首定界符
                        # 帧格式：帧首定界符+目的地址+源地址+长度+载荷+crc校验码
                        state = 4  # 接下来4个字节非数据
                    elif state == 4:  # 目的地址
                        dest_addr = res
                        state -= 1
                    elif state == 3:  # 源地址
                        src_addr = res
                        state -= 1
                    elif state == 2:  # 长度（2字节）
                        len_len1 = res
                        state -= 1
                    elif state == 1:
                        left_len = (len_len1 << 8) + res
                        state -= 1
                    elif state == 0 and left_len > 0:  # 载荷数据
                        left_len -= 8
                        fileSave.write(np.uint8(res))
                    elif state == 0 and left_len == 0:  # crc校验码
                        crcs.append(res)
                    s = ''
                    flag = False
    fileSave.close()


def video2img(video_file: str) -> int:
    cap = cv2.VideoCapture(video_file)
    n = 0
    ret, frame = cap.read()
    while ret:
        cv2.imwrite('res/res' + str(n) + '.png', frame)
        n += 1
        ret, frame = cap.read()
    return n


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='decode')
    parser.add_argument('-v', '--video', type=str, help='Video taken by mobile phone', default='out.avi')
    parser.add_argument('-d', '--directory', type=str, help='Directory of decode file ', default='./')

    arg = parser.parse_args()
    video = arg.video
    directory = arg.directory
    print(video, directory)

    num_of_frames = video2img(video)
    decode(directory + 'res.bin', num_of_frames)
